<template>
  <div class="cascader-bar">
    <div class="header" v-if="configs.canLook || configs.canSearch">
      <a-input class="input" v-model="search" :placeholder="configs.canSearch && configs.placeholder">
        <a-icon v-if="configs.canSearch" slot="addonAfter" type="search" @click="getSearch" />
      </a-input>
    </div>
    <div class="body" ref="CascaderItem" :style="{ height: configs.height + 'px' }">
      <CascaderItem :data.sync="formData" :selectData="selectData" :level="0" @change="change" @add="add" @deal="deal" :config="configs" />
    </div>
    <div class="footer" :style="{ width: btnWidth + 'px' }">
      <slot name="footer"></slot>
    </div>
  </div>
</template>

<script>
import CascaderItem from './cascader-item.vue'
export default {
  name: 'CascaderBar',
  components: {
    CascaderItem
  },
  props: {
    // 数组
    data: {
      type: Array,
      default: () => []
    },
    // 配置项
    config: {
      type: Object,
      default: () => {
        return {}
      }
    },
    value: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {
      formData: this.data.length
        ? JSON.parse(JSON.stringify(this.data))
        : JSON.parse(JSON.stringify(this.value)),
      search: '', // 查询
      btnWidth: '', // 底部插槽宽度
      selectData: [], // 选中数组
      defaultConfig: {
        firstChecked: true, // 首行选中
        width: 300, // 列宽
        height: 400, // 列高
        alwaysShow: true, // 按钮常显
        canEdit: true, // 可编辑
        canMove: true, // 可移动
        canDelete: true, // 可删除
        canLook: true, // 回显
        canSearch: true, // 搜索
        placeholder: '请输入选项名进行搜索', // 搜索框占位
        activeColor: '#eef4ff', // 选中颜色
        level: 4, // 列数
        levelName: [] // 列名称数组
      }
    }
  },
  computed: {
    configs() {
      return Object.assign(this.defaultConfig, this.config)
    }
  },
  watch: {
    selectData: {
      handler(data) {
        this.search = this.config?.canLook
          ? data?.map((item) => item?.label)?.join('/')
          : ''
      },
      deep: true
    },
    formData: {
      handler(data) {
        if (this.value) {
          this.$emit('input', data)
        }
      },
      deep: true
    }
  },
  created() {},
  mounted() {
    // 默认设置
    this.setConfig()
  },
  methods: {
    // 查询
    getSearch() {
      this.getData(this.formData, this.search)
    },
    // 查询符合条件的数据
    getData(list, search) {
      for (let i = 0; i < list.length; i++) {
        // 符合条件
        if (list[i].label == search) {
          // 获取到符合条件的选项的全路径
          const path = list[i]?.path?.split('/')
          // 递归选中
          this.setSelect(this.formData, path, 0)
          return true
        } else if (list[i].children) {
          // 如果已查到符合条件的数据则跳出递归
          if (this.getData(list[i].children, search)) {
            return true
          }
          this.getData(list[i].children, search)
        }
      }
    },
    // 将符合条件的数据路径全选中
    setSelect(list, path, index) {
      for (let i = 0; i < list.length; i++) {
        // 如果符合条件
        if (list[i].id == path[index]) {
          // 选中
          this.change({ item: list[i], level: list[i].level }, true)
          // 递归查找符合下一的条件的数据
          this.setSelect(list[i].children, path, ++index)
          break
        } else if (list[i].children) {
          // 不符合条件，则继续查找
          this.setSelect(list[i].children, path, index)
        }
      }
    },
    // 设置底部按钮的宽度
    setBtnWidth() {
      this.btnWidth = this.$refs?.CascaderItem?.firstElementChild?.clientWidth
    },
    // 确认
    confirm() {
      return this.formData
    },
    // 取消
    cancel() {
      return this.data
    },
    // 修改选中数组
    change(newValue, isSearch = false) {
      this.selectData.splice(newValue.level, 1, newValue.item) // 替换当前点击位置信息
      // 如果是搜索后选中则跳转到选中项的位置
      if (isSearch) {
        let dom = document.getElementById(newValue.item.id)
        dom?.scrollIntoView()
      }
      // 设置底部按钮的宽度
      this.$nextTick(() => {
        this.setBtnWidth()
      })
      this.selectData.splice(newValue.level + 1) // 删除当前点击位置之后的数据
    },
    // 新增/编辑选项
    add(newValue, isAdd) {
      // 如果是第一列并且不是新增子选项则把新增数据添加到列表中
      if (newValue.level == 0) {
        if (isAdd) {
          this.formData.push(newValue)
        } else {
          this.formData.forEach((item, index) => {
            if (item.id === newValue.id && item.value === newValue.value) {
              this.$set(this.formData, index, newValue)
            }
          })
        }
      } else {
        // 否则就递归数组
        this.setName(this.formData, newValue, isAdd)
      }
      // 设置底部按钮的宽度
      this.$nextTick(() => {
        this.setBtnWidth()
      })
    },
    // 删除/移动
    deal(newValue, type) {
      this.dealList(this.formData, newValue, type)
      // 设置底部按钮的宽度
      this.$nextTick(() => {
        this.setBtnWidth()
      })
    },
    // 处理数据
    dealList(list, data, type) {
      for (let i = 0; i < list.length; i++) {
        if (!type && list[i].id === data.id && list[i].value === data.value) {
          let obj = {}
          // 如果删除最后一项
          if (i == list?.length - 1) {
            // 如果数组项大于1
            if (list?.length > 1) {
              // 默认选中当前项上一项
              obj = JSON.parse(JSON.stringify(list?.[i - 1]))
            }
          } else if ((i == 0 && list?.length > 1) || i != 0) {
            // 如果不是删除最后一项，而删除第一项，并且数组项大于1，或者不是删除第一项和最后一项
            // 默认选中当前项下一项
            obj = JSON.parse(JSON.stringify(list?.[i + 1]))
          }
          this.$set(this.selectData, data.level, obj)
          list.splice(i, 1) // 删除数据
          break
        } else if (
          type &&
          list[i].id === data.id &&
          list[i].value === data.value
        ) {
          // 置顶
          if (type === 'ontop') {
            list.splice(i, 1)
            list.unshift(data)
          } else if (type === 'up') {
            // 上移
            let obj = list?.[i - 1]
            list.splice(i, 1, obj)
            list.splice(i - 1, 1, data)
          } else if (type === 'down') {
            // 下移
            let obj = list?.[i + 1]
            list.splice(i, 1, obj)
            list.splice(i + 1, 1, data)
          }
          this.selectData[data.level] = data
          break
        } else if (list[i].children?.length) {
          this.dealList(list[i].children, data, type)
        }
      }
    },
    // 数组递归
    setName(list, data, isAdd) {
      //遍历树  获取id数组
      for (var i in list) {
        // 新增数据
        // 如果当前选中列的选中项的value值和level都等于当前项的值，则把新增数据添加到该项下的children中
        if (
          list[i].id == data.parentId &&
          list[i].value === data.parent &&
          isAdd
        ) {
          // 如果children不存在则新增
          if (!list[i].children) {
            // list[i].children = []
            return false
          }
          list[i].children.push(data)
          break
        } else if (
          list[i].parentId == data.parentId &&
          list[i].id === data.id &&
          list[i].value === data.value &&
          !isAdd
        ) {
          // 编辑数据
          this.$set(list, i, data)
          break
        } else if (list[i].children) {
          //存在子节点就递归
          this.setName(list[i].children, data, isAdd)
        }
      }
    },
    // 初始化
    setConfig() {
      // 如果首行选中
      this.selectData = this.config.firstChecked ? [this.formData[0]] : []
      // 设置底部按钮的宽度
      this.$nextTick(() => {
        this.setBtnWidth()
      })
    }
  }
}
</script>

<style lang="less" scoped>
.cascader-bar {
  //   width: 100%;
  .header {
    .input {
      width: 300px;
      /deep/input {
        border-top-left-radius: 20px;
        border-bottom-left-radius: 20px;
      }
      /deep/.ant-input-group-addon {
        border-top-right-radius: 20px;
        border-bottom-right-radius: 20px;
      }
    }
    margin-bottom: 10px;
  }
  .body {
    display: flex;
  }
}
</style>
